/*
Copyright 2024 MySQL Parser Project

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package main

import (
	"fmt"
	"log"
	"mysql-parser/sqlparser"
	"strings"
)

func main() {
	fmt.Println("🔄 MySQL Parser - Transaction Control Statements Examples")
	fmt.Println(strings.Repeat("=", 80))

	// Initialize parser
	parser, err := sqlparser.New(sqlparser.Options{
		MySQLServerVersion: "8.0.0",
	})
	if err != nil {
		log.Fatal(err)
	}

	// Test transaction control statements
	testTransactionControlStatements(parser)

	// Test statement type detection
	testStatementTypeDetection()

	// Test transaction control in multi-statement scenarios
	testMultiStatementTransactions(parser)

	// Test AST node analysis
	testTransactionASTAnalysis(parser)

	fmt.Println("\n✅ All transaction control examples completed successfully!")
}

// testTransactionControlStatements demonstrates parsing of basic transaction control statements
func testTransactionControlStatements(parser *sqlparser.Parser) {
	fmt.Println("\n📋 1. Basic Transaction Control Statements")
	fmt.Println(strings.Repeat("-", 50))

	transactionStatements := []string{
		"BEGIN",
		"COMMIT",
		"ROLLBACK",
		"BEGIN;",
		"COMMIT;",
		"ROLLBACK;",
	}

	for i, sql := range transactionStatements {
		fmt.Printf("\n%d. Parsing: %s\n", i+1, sql)

		stmt, err := parser.Parse(sql)
		if err != nil {
			fmt.Printf("   ❌ Parse error: %v\n", err)
			continue
		}

		fmt.Printf("   ✅ Parse successful\n")
		fmt.Printf("   📝 Statement type: %T\n", stmt)
		fmt.Printf("   🔄 Regenerated SQL: %s\n", stmt.String())

		// Type-specific analysis
		switch s := stmt.(type) {
		case *sqlparser.BeginStatement:
			fmt.Printf("   🚀 Transaction started\n")
		case *sqlparser.CommitStatement:
			fmt.Printf("   💾 Transaction committed\n")
		case *sqlparser.RollbackStatement:
			fmt.Printf("   ↩️  Transaction rolled back\n")
		default:
			fmt.Printf("   ⚠️  Unexpected statement type: %T\n", s)
		}
	}
}

// testStatementTypeDetection demonstrates the statement type detection functions
func testStatementTypeDetection() {
	fmt.Println("\n🔍 2. Statement Type Detection")
	fmt.Println(strings.Repeat("-", 50))

	testCases := []struct {
		sql         string
		description string
	}{
		{"BEGIN", "Transaction start"},
		{"COMMIT", "Transaction commit"},
		{"ROLLBACK", "Transaction rollback"},
		{"SELECT * FROM users", "DML query"},
		{"INSERT INTO users VALUES (1, 'test')", "DML insert"},
		{"CREATE TABLE test (id INT)", "DDL statement"},
		{"  BEGIN  ", "Transaction start with whitespace"},
		{"COMMIT;", "Transaction commit with semicolon"},
	}

	for i, tc := range testCases {
		fmt.Printf("\n%d. Testing: %s (%s)\n", i+1, tc.sql, tc.description)

		// Test IsTransactionControl
		isTransaction := sqlparser.IsTransactionControl(tc.sql)
		fmt.Printf("   🔄 IsTransactionControl: %v\n", isTransaction)

		// Test IsDML
		isDML := sqlparser.IsDML(tc.sql)
		fmt.Printf("   📊 IsDML: %v\n", isDML)

		// Test IsDDL
		isDDL := sqlparser.IsDDL(tc.sql)
		fmt.Printf("   🏗️  IsDDL: %v\n", isDDL)

		// Test GetStatementType
		stmtType := sqlparser.GetStatementType(tc.sql)
		fmt.Printf("   📝 Statement Type: %s\n", stmtType)

		// Categorize statement
		if isTransaction {
			fmt.Printf("   ✅ Category: Transaction Control\n")
		} else if isDML {
			fmt.Printf("   ✅ Category: Data Manipulation Language (DML)\n")
		} else if isDDL {
			fmt.Printf("   ✅ Category: Data Definition Language (DDL)\n")
		} else {
			fmt.Printf("   ❓ Category: Other/Unknown\n")
		}
	}
}

// testMultiStatementTransactions demonstrates parsing multiple statements including transactions
func testMultiStatementTransactions(parser *sqlparser.Parser) {
	fmt.Println("\n🔗 3. Multi-Statement Transaction Scenarios")
	fmt.Println(strings.Repeat("-", 50))

	multiStatementSQL := `BEGIN;
		INSERT INTO users (name, email) VALUES ('John', 'john@example.com');
		UPDATE users SET last_login = NOW() WHERE name = 'John';
		COMMIT;`

	fmt.Printf("\nParsing multi-statement transaction:\n%s\n\n", multiStatementSQL)

	// Split statements
	statements, err := sqlparser.SplitStatement(multiStatementSQL)
	if err != nil {
		fmt.Printf("❌ Error splitting statements: %v\n", err)
		return
	}

	fmt.Printf("📊 Found %d statements:\n", len(statements))

	for i, stmt := range statements {
		fmt.Printf("\n%d. Statement: %s\n", i+1, stmt)

		// Parse each statement
		parsedStmt, err := parser.Parse(stmt)
		if err != nil {
			fmt.Printf("   ❌ Parse error: %v\n", err)
			continue
		}

		fmt.Printf("   ✅ Type: %T\n", parsedStmt)

		// Analyze statement type
		if sqlparser.IsTransactionControl(stmt) {
			fmt.Printf("   🔄 Transaction control statement\n")
		} else if sqlparser.IsDML(stmt) {
			fmt.Printf("   📊 DML statement\n")
		} else if sqlparser.IsDDL(stmt) {
			fmt.Printf("   🏗️  DDL statement\n")
		}
	}
}

// testTransactionASTAnalysis demonstrates AST analysis for transaction control statements
func testTransactionASTAnalysis(parser *sqlparser.Parser) {
	fmt.Println("\n🌳 4. Transaction Control AST Analysis")
	fmt.Println(strings.Repeat("-", 50))

	transactionStatements := []string{"BEGIN", "COMMIT", "ROLLBACK"}

	for i, sql := range transactionStatements {
		fmt.Printf("\n%d. Analyzing AST for: %s\n", i+1, sql)

		stmt, err := parser.Parse(sql)
		if err != nil {
			fmt.Printf("   ❌ Parse error: %v\n", err)
			continue
		}

		fmt.Printf("   📝 AST Node Type: %T\n", stmt)
		fmt.Printf("   🔄 String Representation: %s\n", stmt.String())

		// Test that the statement implements the Statement interface
		if _, ok := stmt.(sqlparser.Statement); ok {
			fmt.Printf("   ✅ Implements Statement interface\n")
		} else {
			fmt.Printf("   ❌ Does not implement Statement interface\n")
		}

		// Test that the statement implements the SQLNode interface
		if _, ok := stmt.(sqlparser.SQLNode); ok {
			fmt.Printf("   ✅ Implements SQLNode interface\n")
		} else {
			fmt.Printf("   ❌ Does not implement SQLNode interface\n")
		}

		// Demonstrate Format method (if available)
		if sqlNode, ok := stmt.(sqlparser.SQLNode); ok {
			var buf strings.Builder
			trackedBuf := sqlparser.NewTrackedBuffer(&buf)
			sqlNode.Format(trackedBuf)
			fmt.Printf("   📄 Formatted output: %s\n", buf.String())
		}

		// Type-specific analysis
		switch s := stmt.(type) {
		case *sqlparser.BeginStatement:
			fmt.Printf("   🚀 BeginStatement - starts a new transaction\n")
			fmt.Printf("   📊 Node properties: Simple transaction start statement\n")
		case *sqlparser.CommitStatement:
			fmt.Printf("   💾 CommitStatement - commits current transaction\n")
			fmt.Printf("   📊 Node properties: Transaction commit statement\n")
		case *sqlparser.RollbackStatement:
			fmt.Printf("   ↩️  RollbackStatement - rolls back current transaction\n")
			fmt.Printf("   📊 Node properties: Transaction rollback statement\n")
		default:
			fmt.Printf("   ⚠️  Unexpected statement type: %T\n", s)
		}
	}

	fmt.Println("\n🎯 Transaction Control Features Summary:")
	fmt.Println("   ✅ BEGIN statement parsing and AST generation")
	fmt.Println("   ✅ COMMIT statement parsing and AST generation")
	fmt.Println("   ✅ ROLLBACK statement parsing and AST generation")
	fmt.Println("   ✅ Statement type detection (IsTransactionControl)")
	fmt.Println("   ✅ Multi-statement transaction support")
	fmt.Println("   ✅ Complete AST node implementation")
	fmt.Println("   ✅ String representation and formatting")
}